﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using BassDrop.Core.Common.Services;
using BassDrop.DesktopClient.Utilities;
namespace BassDrop.DesktopClient.Properties
{


	// This class allows you to handle specific events on the settings class:
	//  The SettingChanging event is raised before a setting's value is changed.
	//  The PropertyChanged event is raised after a setting's value is changed.
	//  The SettingsLoaded event is raised after the setting values are loaded.
	//  The SettingsSaving event is raised before the setting values are saved.
	public sealed partial class Settings : ISettings
	{

		public Settings()
		{
			if ( CustomProperties == null )
			{
				CustomProperties = new PersistableStringDictionary();
			}
		}


		#region ISettings Members

		/// <summary>
		/// Returns a setting value for the specified plugin / plugin instance
		/// </summary>
		/// <param name="settingName">the name of the setting you want</param>
		/// <param name="pluginName">the name of the plugin</param>
		/// <param name="instanceName">the name of the plugin instance or null if you want a static setting</param>
		/// <returns></returns>
		public string PluginSettingAt( string settingName, string pluginName, string instanceName = null )
		{
			return SettingAt( "__pluginSettings/" + pluginName + (instanceName != null ? "/__instances/" + instanceName : "") + "/" + settingName );
		}

		/// <summary>
		/// Sets a setting value for the specified plugin / plugin instance
		/// </summary>
		/// <param name="settingName">the name of the setting you want to set</param>
		/// <param name="settingValue">the value of the setting</param>
		/// <param name="pluginName">the name of the plugin</param>
		/// <param name="instanceName">the name of the plugin instance or null if you want a static setting</param>
		/// <returns></returns>
		public void SetPluginSettingAt( string settingName, string settingValue, string pluginName, string instanceName = null )
		{
			SetSettingAt( "__pluginSettings/" + pluginName + (instanceName != null ? "/__instances/" + instanceName : "") + "/" + settingName, settingValue );
		}

		/// <summary>
		/// Deletes the settings of the specified plugin / plugin instance
		/// </summary>
		/// <param name="pluginName">the name of the plugin</param>
		/// <param name="instanceName">the name of the plugin instance or null if you want a static setting</param>
		public void ClearPluginSettings( string pluginName, string instanceName = null )
		{
			ClearSettings( "__pluginSettings/" + pluginName + (instanceName != null ? "/__instances/" + instanceName : "") );
		}

		/// <summary>
		/// Returns all settings of the specified plugin in a dictionary
		/// </summary>
		/// <param name="pluginName">the name of the plugin</param>
		/// <param name="instanceName">the name of the plugin instance or null if you want the static settings</param>
		/// <returns></returns>
		public IDictionary<string, string> PluginSettings( string pluginName, string instanceName = null )
		{
			string folder = "__pluginSettings/" + pluginName + (instanceName != null ? "/__instances/" + instanceName : "") + "/";
			Dictionary<string, string> ret = new Dictionary<string, string>();

			foreach ( var item in CustomProperties.Keys )
			{
				if ( item.StartsWith( folder ) )
				{
					ret.Add( item.Substring( folder.Length ), CustomProperties[item] );
				}
			}

			return ret;
		}

		/// <summary>
		/// Returns the list of saved plugin instance names
		/// </summary>
		/// <param name="pluginName">the name of the plugin</param>
		/// <returns></returns>
		public IEnumerable<string> PluginInstances( string pluginName )
		{
			string folder = "__pluginSettings/" + pluginName + "/__instances/";
			HashSet<string> values = new HashSet<string>();

			foreach ( var item in CustomProperties.Keys )
			{
				if ( item.StartsWith( folder ) )
				{
					string name = item.Substring( folder.Length );
					int length = name.LastIndexOf( '/' );

					if ( length == -1 )
					{
						length = name.Length;
					}

					name = name.Substring( 0, length );

					values.Add( name );
				}
			}

			return values.AsEnumerable();
		}

		/// <summary>
		/// Returns the setting at the specified path
		/// </summary>
		/// <param name="path">A path as "settingGroup1/settingGroup2/setting"</param>
		/// <returns>The setting at the specified path or null if it doesn't exist</returns>
		public string SettingAt( string path )
		{
			if ( CustomProperties.ContainsKey( path ) )
			{
				return CustomProperties[path];
			}
			else
			{
				return null;
			}
		}

		/// <summary>
		/// Sets a setting at the specified path with the specified value. Creates the path (groups)
		/// to it if necessary.
		/// </summary>
		/// <param name="path">A path as "settingGroup1/settingGroup2/setting"</param>
		/// <param name="value">Value of the setting</param>
		/// <returns>The value parameter</returns>
		public void SetSettingAt( string path, string value )
		{
			CustomProperties[path] = value;
		}

		/// <summary>
		/// Deletes the settings on the passed path
		/// </summary>
		/// <param name="path">A path as "settingGroup1/settingGroup2/setting"</param>
		public void ClearSettings( string path )
		{
			List<string> keys = new List<string>();

			foreach ( var item in CustomProperties.Keys )
			{
				if ( item.StartsWith( path ) )
				{
					keys.Add( item );
				}
			}

			foreach ( var item in keys )
			{
				CustomProperties.Remove( item );
			}
		}

		#endregion
	}
}
